import { Title } from '@/components/common/Title'
import { useState, useEffect, useRef, useCallback } from 'react'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { Label } from '@/components/ui/label'
import { Input } from '@/components/ui/input'
import { Slider } from '@/components/ui/slider'
import { Switch } from '@/components/ui/switch'
import { AlertCircle, BellRing, Power, Plus, X, Play, Pause, Crop, ExternalLink, Volume2, Phone, FileAudio, TestTube, PlayCircle } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { createWorker, PSM } from 'tesseract.js'
import { RegionSelector } from '@/components/RegionSelector'

export default function LiveWakeup() {
  // 监控状态
  const [isMonitoring, setIsMonitoring] = useState(false)
  const [ocrReady, setOcrReady] = useState(false)
  
  // 只使用OCR模式
  
  // 清理旧的图像匹配数据
  useEffect(() => {
    localStorage.removeItem('liveWakeup:detectionMode')
    localStorage.removeItem('liveWakeup:templateImages')
    localStorage.removeItem('liveWakeup:templateImagesConfig')
  }, [])
  
  // 配置状态
  const [keywords, setKeywords] = useState<string[]>(() => {
    const saved = localStorage.getItem('liveWakeup:keywords')
    return saved ? JSON.parse(saved) : ['人脸识别', '身份验证', '安全验证']
  })
  const [checkInterval, setCheckInterval] = useState([3]) // 检测间隔（秒）
  const [saveScreenshot, setSaveScreenshot] = useState(true)
  const [alertVolume, setAlertVolume] = useState<number[]>(() => {
    const saved = localStorage.getItem('liveWakeup:alertVolume')
    return saved ? [parseInt(saved)] : [80]
  })
  const [alertRepeat, setAlertRepeat] = useState<number[]>(() => {
    const saved = localStorage.getItem('liveWakeup:alertRepeat')
    return saved ? [parseInt(saved)] : [0] // 0表示无限循环
  })
  
  // 图像预处理模式
  const [preprocessMode, setPreprocessMode] = useState<'none' | 'light' | 'standard' | 'strong'>(() => {
    const saved = localStorage.getItem('liveWakeup:preprocessMode')
    return (saved as 'none' | 'light' | 'standard' | 'strong') || 'light'
  })

  // OCR引擎配置
  const [ocrEngine, setOcrEngine] = useState<'tesseract' | 'umi-ocr'>(() => {
    const saved = localStorage.getItem('liveWakeup:ocrEngine')
    return (saved as 'tesseract' | 'umi-ocr') || 'tesseract'
  })
  const [umiOcrApiUrl, setUmiOcrApiUrl] = useState(() => {
    const saved = localStorage.getItem('liveWakeup:umiOcrApiUrl')
    return saved || 'http://localhost:1224'
  })
  const [umiOcrLanguage, setUmiOcrLanguage] = useState(() => {
    const saved = localStorage.getItem('liveWakeup:umiOcrLanguage')
    return saved || 'chi_sim'
  })

  // 叫醒模式状态
  const [wakeupMode, setWakeupMode] = useState<'audio' | 'phone'>(() => {
    const saved = localStorage.getItem('liveWakeup:wakeupMode')
    return (saved as 'audio' | 'phone') || 'audio'
  })
  const [audioFilePath, setAudioFilePath] = useState(() => {
    const saved = localStorage.getItem('liveWakeup:audioFilePath')
    return saved || ''
  })
  const [phoneNumber, setPhoneNumber] = useState(() => {
    const saved = localStorage.getItem('liveWakeup:phoneNumber')
    return saved || ''
  })

  // 阿里云配置状态（从配置文件读取）
  const [aliCloudConfigStatus, setAliCloudConfigStatus] = useState<{
    isConfigured: boolean
    source: 'file' | 'manual' | 'none'
    error?: string
    initialized: boolean
  }>({
    isConfigured: false,
    source: 'none',
    initialized: false
  })
  
  // 区域选择状态
  const [captureRegion, setCaptureRegion] = useState<{
    x: number
    y: number
    width: number
    height: number
  } | null>(() => {
    // 从 localStorage 加载保存的区域配置
    const saved = localStorage.getItem('liveWakeup:captureRegion')
    if (saved) {
      try {
        return JSON.parse(saved)
      } catch (e) {
        console.error('[区域选择] 加载配置失败:', e)
      }
    }
    return null
  })
  const [isSelectingRegion, setIsSelectingRegion] = useState(false)
  const [regionSelectImage, setRegionSelectImage] = useState<string | null>(null)
  
  // 新关键词输入
  const [newKeyword, setNewKeyword] = useState('')
  
  // 警报状态
  const [alertActive, setAlertActive] = useState(false)
  const [lastAlert, setLastAlert] = useState<{
    keyword: string
    screenshot?: string
    timestamp: number
  } | null>(null)
  
  // OCR Worker 引用
  const ocrWorkerRef = useRef<Awaited<ReturnType<typeof createWorker>> | null>(null)
  
  // 使用 ref 立即追踪监控状态（避免 setState 异步问题）
  const isMonitoringRef = useRef(false)
  
  // 音频引用
  const alertAudioRef = useRef<HTMLAudioElement | null>(null)
  const alertIntervalRef = useRef<NodeJS.Timeout | null>(null)
  const audioContextRef = useRef<AudioContext | null>(null)
  const currentAlertActive = useRef(false)


  // 检查阿里云配置状态
  useEffect(() => {
    async function checkAliCloudConfig() {
      try {
        const result = await window.ipcRenderer.invoke('liveWakeup:getConfigStatus' as any)
        if (result.success) {
          setAliCloudConfigStatus({
            ...result.status,
            initialized: false // 配置检查成功但需要初始化
          })
        } else {
          setAliCloudConfigStatus({
            isConfigured: false,
            source: 'none',
            error: result.error,
            initialized: false
          })
        }
      } catch (error) {
        console.error('[配置检查] 检查阿里云配置状态失败:', error)
        setAliCloudConfigStatus({
          isConfigured: false,
          source: 'none',
          error: '配置检查失败',
          initialized: false
        })
      }
    }

    checkAliCloudConfig()
  }, [])

  // 初始化 OCR Worker（仅当使用 Tesseract 引擎时）
  useEffect(() => {
    async function initOCR() {
      // 如果使用 Umi-OCR，跳过 Tesseract 初始化
      if (ocrEngine === 'umi-ocr') {
        console.log('[OCR] 使用 Umi-OCR 引擎，跳过 Tesseract 初始化')
        setOcrReady(true)
        return
      }

      try {
        console.log('[OCR] 开始初始化 Tesseract（优化版）...')
        // 使用中文语言包（大多数直播平台使用中文）
        // 配合图像预处理可获得很高的识别率
        const worker = await createWorker('chi_sim', 1, {
          logger: (m) => {
            // 只在初始化时输出关键信息
            if (m.status === 'initializing language' || m.status === 'initialized api' || m.status === 'loading language traineddata') {
              console.log('[OCR]', m.status, m.progress ? `${(m.progress * 100).toFixed(0)}%` : '')
            }
          },
          workerPath: '/tesseract/worker.min.js', // 使用本地文件
          langPath: 'https://tessdata.projectnaptha.com/4.0.0', // 语言包从 CDN 下载（仅首次）
        })
        
        // ⚡ 优化配置：提升识别速度和准确率
        await worker.setParameters({
          tessedit_pageseg_mode: PSM.AUTO,          // 自动检测页面分割模式
          tessedit_char_whitelist: '',              // 不限制字符
          preserve_interword_spaces: '1',           // 保留词间空格
          tessjs_create_hocr: '0',                  // 禁用HOCR输出（加速）
          tessjs_create_tsv: '0',                   // 禁用TSV输出（加速）
          tessjs_create_box: '0',                   // 禁用BOX输出（加速）
          tessjs_create_unlv: '0',                  // 禁用UNLV输出（加速）
          tessjs_create_osd: '0',                   // 禁用OSD输出（加速）
          tessedit_ocr_engine_mode: '1',            // 使用LSTM引擎（更准确）
        })
        
        ocrWorkerRef.current = worker
        setOcrReady(true)
        console.log('[OCR] ✅ Tesseract 初始化成功（中文识别 + 图像预处理优化）!')
      } catch (error) {
        console.error('[OCR] 初始化失败:', error)
        alert('OCR 引擎初始化失败，可能是网络问题。请检查网络连接或稍后再试。\n\n错误详情: ' + (error instanceof Error ? error.message : '未知错误'))
      }
    }

    initOCR()

    return () => {
      if (ocrWorkerRef.current) {
        ocrWorkerRef.current.terminate()
        ocrWorkerRef.current = null
      }
    }
  }, [ocrEngine])

  // 停止警报
  const stopAlert = useCallback(() => {
    console.log('[警报] 停止警报')
    
    // 更新状态
    setAlertActive(false)
    currentAlertActive.current = false
    
    // 清除定时器
    if (alertIntervalRef.current) {
      clearInterval(alertIntervalRef.current)
      alertIntervalRef.current = null
    }
    
    // 停止自定义音频文件播放（通过主进程）
    // 主进程会广播 'tts:stop-audio' 事件到所有窗口
    try {
      window.ipcRenderer.send('tts:stop-audio')
    } catch (error) {
      console.error('[警报] 发送停止音频请求失败:', error)
    }
    
    // 停止 HTML5 音频播放（如果有的话）
    if (alertAudioRef.current) {
      alertAudioRef.current.pause()
      alertAudioRef.current.currentTime = 0
      alertAudioRef.current = null
    }
    
    // 停止 AudioContext（默认警报音）
    if (audioContextRef.current) {
      try {
        audioContextRef.current.close()
        audioContextRef.current = null
      } catch (error) {
        console.error('[警报] 关闭 AudioContext 失败:', error)
      }
    }
  }, [])

  // 播放默认警报音（嘟嘟嘟）
  const playDefaultAlertSound = useCallback(() => {
    console.log('[警报] 播放默认警报音')
    
    // 先停止之前的音频
    if (audioContextRef.current) {
      try {
        audioContextRef.current.close()
      } catch (error) {
        console.error('[警报] 关闭旧的 AudioContext 失败:', error)
      }
    }
    
    // 创建新的 AudioContext
    const audioContext = new AudioContext()
    audioContextRef.current = audioContext
    currentAlertActive.current = true
    
    const playOnce = () => {
      return new Promise<void>(resolve => {
        const oscillator = audioContext.createOscillator()
        const gainNode = audioContext.createGain()
        
        oscillator.connect(gainNode)
        gainNode.connect(audioContext.destination)
        
        oscillator.frequency.value = 800
        oscillator.type = 'sine'
        
        gainNode.gain.setValueAtTime(alertVolume[0] / 100, audioContext.currentTime)
        gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3)
        
        oscillator.start(audioContext.currentTime)
        oscillator.stop(audioContext.currentTime + 0.3)
        
        oscillator.onended = () => resolve()
      })
    }

    // 连续播放多次
    (async () => {
      for (let i = 0; i < 3; i++) {
        if (!currentAlertActive.current) return // 检查是否已停止
        await playOnce()
        await new Promise(resolve => setTimeout(resolve, 200))
      }

      // 如果设置了循环，继续播放
      if (alertRepeat[0] === 0) {
        // 无限循环
        alertIntervalRef.current = setInterval(async () => {
          if (currentAlertActive.current) {
            for (let i = 0; i < 3; i++) {
              if (!currentAlertActive.current) break
              await playOnce()
              await new Promise(resolve => setTimeout(resolve, 200))
            }
          } else {
            if (alertIntervalRef.current) {
              clearInterval(alertIntervalRef.current)
              alertIntervalRef.current = null
            }
          }
        }, 2000)
      } else if (alertRepeat[0] > 1) {
        // 有限次循环：已经播放了第一次，还需要播放 (alertRepeat[0] - 1) 次
        const remainingCount = alertRepeat[0] - 1
        let count = 0
        alertIntervalRef.current = setInterval(async () => {
          if (count < remainingCount && currentAlertActive.current) {
            for (let i = 0; i < 3; i++) {
              if (!currentAlertActive.current) break
              await playOnce()
              await new Promise(resolve => setTimeout(resolve, 200))
            }
            count++
          } else {
            // 循环结束，清除定时器
            if (alertIntervalRef.current) {
              clearInterval(alertIntervalRef.current)
              alertIntervalRef.current = null
            }
            // 不要自动调用 stopAlert()，让用户手动点击"停止警报"按钮
            console.log('[警报] 默认警报音循环播放完成，等待用户手动停止')
          }
        }, 2000)
      } else {
        // alertRepeat[0] === 1，只播放一次，不设置循环
        console.log('[警报] 默认警报音只播放1次，不设置循环定时器')
      }
    })()
  }, [alertVolume, alertRepeat])

  // 播放警报音（提前定义，因为 performOCRRecognition 需要用到）
  const playAlertSound = useCallback(async () => {
    console.log('[警报] 准备播放警报音')
    console.log('[警报] alertRepeat 值:', alertRepeat, 'alertRepeat[0]:', alertRepeat[0], '类型:', typeof alertRepeat[0])
    
    // 先停止所有之前的音频
    if (alertIntervalRef.current) {
      clearInterval(alertIntervalRef.current)
      alertIntervalRef.current = null
    }
    
    if (alertAudioRef.current) {
      alertAudioRef.current.pause()
      alertAudioRef.current.currentTime = 0
      alertAudioRef.current = null
    }
    
    if (audioContextRef.current) {
      try {
        audioContextRef.current.close()
      } catch (error) {
        console.error('[警报] 关闭旧的 AudioContext 失败:', error)
      }
      audioContextRef.current = null
    }
    
    // 标记警报为激活状态
    currentAlertActive.current = true
    
    // 如果选择了音频文件，播放该音频文件
    if (audioFilePath && audioFilePath.trim()) {
      console.log('[警报] 播放自定义音频文件:', audioFilePath)
      
      // 定义播放函数（返回 Promise）
      const playCustomAudio = async (): Promise<boolean> => {
        if (!currentAlertActive.current) return false
        
        try {
          console.log('[警报] 开始播放音频...')
          const result = await window.ipcRenderer.invoke('liveWakeup:playAudioFile', {
            filePath: audioFilePath,
            volume: alertVolume[0]
          })
          
          if (!result.success) {
            console.error('[警报] 音频文件播放失败:', result.error)
            return false
          }
          
          console.log('[警报] 音频播放完成')
          return true
        } catch (error) {
          console.error('[警报] 播放音频文件异常:', error)
          return false
        }
      }
      
      // 定义循环播放函数
      const playLoop = async () => {
        let playCount = 0
        const totalCount = alertRepeat[0]
        
        console.log('[警报] 🔍 循环设置检查: alertRepeat[0] =', totalCount, '类型:', typeof totalCount)
        
        if (totalCount === 0) {
          // 无限循环
          console.log('[警报] ✅ 开始无限循环播放')
          while (currentAlertActive.current) {
            playCount++
            console.log(`[警报] 播放第 ${playCount} 次自定义音频`)
            const success = await playCustomAudio()
            if (!success) {
              console.error('[警报] 播放失败，回退到默认警报音')
              playDefaultAlertSound()
              return
            }
            console.log(`[警报] 第 ${playCount} 次播放完成`)
          }
          console.log('[警报] 无限循环结束（用户手动停止）')
        } else if (totalCount > 0) {
          // 有限次循环
          console.log(`[警报] ✅ 开始有限循环播放 ${totalCount} 次`)
          while (playCount < totalCount && currentAlertActive.current) {
            playCount++
            console.log(`[警报] 播放第 ${playCount}/${totalCount} 次自定义音频`)
            const success = await playCustomAudio()
            if (!success) {
              console.error('[警报] 播放失败，回退到默认警报音')
              playDefaultAlertSound()
              return
            }
            console.log(`[警报] 第 ${playCount}/${totalCount} 次播放完成`)
          }
          console.log(`[警报] 循环播放完成，总共播放了 ${playCount} 次，等待用户手动停止`)
        }
      }
      
      // 开始循环播放
      playLoop()
    } else {
      // 没有选择音频文件，播放默认的"嘟嘟嘟"警报音
      playDefaultAlertSound()
    }
  }, [audioFilePath, alertVolume, alertRepeat, playDefaultAlertSound])

  // OCR识别日志
  const [ocrLogs, setOcrLogs] = useState<Array<{
    timestamp: number
    text: string
    confidence: number
    matched: boolean
    keyword?: string
  }>>([])

  // 添加OCR日志
  const addOcrLog = useCallback((log: {
    text: string
    confidence: number
    matched: boolean
    keyword?: string
  }) => {
    setOcrLogs(prev => {
      const newLogs = [{
        timestamp: Date.now(),
        ...log
      }, ...prev]
      // 只保留最近20条日志
      return newLogs.slice(0, 20)
    })
  }, [])

  // 执行 OCR 识别
  const performOCRRecognition = useCallback(async (data: {
    screenshot: string
    originalScreenshot?: string
    keywords: string[]
    saveScreenshot: boolean
  }) => {
    if (!ocrWorkerRef.current) {
      console.error('[OCR] Worker 未初始化')
      return
    }

    try {
      console.log('[OCR] 开始识别...')
      const startTime = performance.now()
      const { data: { text, confidence } } = await ocrWorkerRef.current.recognize(data.screenshot)
      const elapsed = Math.round(performance.now() - startTime)
      
      // 识别完成后，立即检查监控是否已停止
      if (!isMonitoringRef.current) {
        console.log('[OCR] ❌ 识别完成但监控已停止，不触发警报')
        return
      }
      
      const normalizedText = text.toLowerCase().replace(/\s/g, '')
      
      console.log(`[OCR] 识别完成，耗时: ${elapsed}ms，置信度: ${(confidence * 100).toFixed(1)}%`)
      console.log('[OCR] 识别文本（前100字符）:', normalizedText.substring(0, 100))
      console.log('[OCR] 完整文本:', text)

      // 检查关键词
      let matched = false
      let matchedKeyword: string | undefined
      
      for (const keyword of data.keywords) {
        const normalizedKeyword = keyword.toLowerCase().replace(/\s/g, '')
        if (normalizedText.includes(normalizedKeyword)) {
          console.log('[OCR] 🚨 检测到关键词:', keyword)
          matched = true
          matchedKeyword = keyword
          
          // 添加OCR日志（匹配成功）
          addOcrLog({
            text: text.substring(0, 200), // 只保留前200字符
            confidence: confidence || 0,
            matched: true,
            keyword: keyword
          })
          
          // 再次检查监控状态（双重保险）
          if (!isMonitoringRef.current) {
            console.log('[OCR] ❌ 准备触发警报时发现监控已停止，取消警报')
            return
          }
          
          // 触发警报（使用原始图像而不是预处理后的图像）
          setLastAlert({
            keyword,
            screenshot: data.saveScreenshot ? (data.originalScreenshot || data.screenshot) : undefined,
            timestamp: Date.now(),
          })
          setAlertActive(true)
          
          // 🔴 立即停止监控，避免重复触发
          console.log('[监控] 检测到关键词，自动停止监控')
          isMonitoringRef.current = false
          setIsMonitoring(false)
          
          // 调用主进程停止监控
          try {
            await window.ipcRenderer.invoke('liveWakeup:stop')
          } catch (error) {
            console.error('[监控] 停止监控失败:', error)
          }
          
          // 根据叫醒模式选择不同的提醒方式
          if (wakeupMode === 'phone' && phoneNumber.trim() && aliCloudConfigStatus.initialized) {
            // 电话叫醒模式
            console.log('[叫醒] 使用电话叫醒模式')
            try {
              const result = await window.ipcRenderer.invoke('liveWakeup:sendWakeupCall' as any, {
                phoneNumber: phoneNumber.trim(),
                message: `检测到关键词"${keyword}"，请立即查看直播状态！`
              }) as VoiceCallResult
              
              if (result.success) {
                console.log(`[叫醒] 电话叫醒成功，通话ID: ${result.callId}`)
              } else {
                console.error(`[叫醒] 电话叫醒失败: ${result.error}`)
                // 电话叫醒失败时，回退到音频警报
                playAlertSound()
              }
            } catch (error) {
              console.error('[叫醒] 电话叫醒异常:', error)
              // 异常时回退到音频警报
              playAlertSound()
            }
          } else {
            // 音频叫醒模式或电话模式配置不完整时
            playAlertSound()
          }
          
          break
        }
      }
      
      // 如果没有匹配，也记录日志
      if (!matched) {
        addOcrLog({
          text: text.substring(0, 200),
          confidence: confidence || 0,
          matched: false
        })
      }
    } catch (error) {
      console.error('[OCR] 识别失败:', error)
    }
  }, [playAlertSound, wakeupMode, phoneNumber, aliCloudConfigStatus.initialized, addOcrLog])

  // 监听来自主进程的 OCR 请求（仅 Tesseract 引擎使用）
  useEffect(() => {
    const unsubscribe = window.ipcRenderer.on(
      'liveWakeup:performOCR',
      (data: { screenshot: string; keywords: string[]; saveScreenshot: boolean }) => {
        // 使用 ref 立即检查监控状态（避免 setState 异步延迟）
        if (!isMonitoringRef.current) {
          console.log('[OCR] ❌ 忽略请求 - 监控已停止 (ref检查)')
          return
        }
        
        // 如果使用 Umi-OCR，主进程会处理 OCR，不会发送到这里
        if (ocrEngine === 'umi-ocr') {
          console.log('[OCR] 使用 Umi-OCR，主进程已处理识别')
          return
        }
        
        if (!ocrReady) {
          console.log('[OCR] ⏳ 忽略请求 - OCR未就绪')
          return
        }
        
        // 只有在监控运行中且OCR就绪时才处理
        console.log('[OCR] ✅ 接收到 Tesseract OCR 请求，开始处理...')
        performOCRRecognition(data)
      }
    )

    return () => {
      unsubscribe()
    }
  }, [ocrReady, performOCRRecognition, ocrEngine])

  // 监听警报触发事件（用于 Umi-OCR 引擎或图像匹配模式）
  useEffect(() => {
    const unsubscribe = window.ipcRenderer.on('liveWakeup:alertTriggered', (data: { 
      keyword: string
      screenshot?: string
      timestamp: number
      phoneCallSent?: boolean
    }) => {
      console.log('[主窗口] 📩 收到警报触发事件，关键词:', data.keyword)
      
      // 设置警报状态
      setLastAlert({
        keyword: data.keyword,
        screenshot: data.screenshot,
        timestamp: data.timestamp
      })
      setAlertActive(true)
      
      // 停止监控
      isMonitoringRef.current = false
      setIsMonitoring(false)
      
      // 如果主进程已发送电话叫醒，不需要播放音频
      if (data.phoneCallSent) {
        console.log('[主窗口] 主进程已发送电话叫醒，不播放音频')
        return
      }
      
      // 播放警报音
      playAlertSound()
    })

    return () => {
      unsubscribe()
    }
  }, [playAlertSound])

  // 测试截图
  const [testScreenshot, setTestScreenshot] = useState<string | null>(null)
  const [isTestingScreenshot, setIsTestingScreenshot] = useState(false)
  
  // OCR测试
  const [ocrTestResult, setOcrTestResult] = useState<{
    originalImage: string
    processedImage: string
    text: string
    confidence: number
    elapsed: number
  } | null>(null)
  const [isTestingOCR, setIsTestingOCR] = useState(false)

  const handleTestScreenshot = async () => {
    setIsTestingScreenshot(true)
    try {
      console.log('[测试] 开始截图测试...', captureRegion ? '使用选择区域' : '全屏截图')
      // 传递当前选择的区域（如果有的话）
      const result = await window.ipcRenderer.invoke('liveWakeup:capturePreview' as any, captureRegion)
      if (result.success && result.screenshot) {
        setTestScreenshot(result.screenshot)
        console.log('[测试] 截图成功', captureRegion ? `区域: ${captureRegion.width}×${captureRegion.height}` : '全屏')
      } else {
        alert(`截图失败: ${result.error || '未知错误'}`)
      }
    } catch (error) {
      console.error('[测试] 截图失败:', error)
      alert('截图失败，请重试')
    } finally {
      setIsTestingScreenshot(false)
    }
  }

  // 测试OCR识别
  const handleTestOCR = async () => {
    if (!ocrReady) {
      alert('OCR 引擎未就绪，请稍候...')
      return
    }

    setIsTestingOCR(true)
    setOcrTestResult(null)
    
    try {
      console.log('[OCR测试] 开始截图和识别...', captureRegion ? '使用选择区域' : '全屏', '预处理模式:', preprocessMode, 'OCR引擎:', ocrEngine)
      
      // 截图并获取预处理后的图像（传递预处理模式）
      const result = await window.ipcRenderer.invoke('liveWakeup:capturePreview' as any, captureRegion, true, preprocessMode)
      
      if (!result.success || !result.screenshot || !result.processedScreenshot) {
        alert(`截图失败: ${result.error || '未知错误'}`)
        return
      }

      console.log('[OCR测试] 截图成功，开始OCR识别...')
      
      let text = ''
      let confidence = 0
      let elapsed = 0
      
      if (ocrEngine === 'umi-ocr') {
        // 使用 Umi-OCR 引擎
        console.log('[OCR测试] 使用 Umi-OCR 引擎识别...')
        const ocrResult = await window.ipcRenderer.invoke('liveWakeup:testUmiOCR' as any, {
          imageBase64: result.processedScreenshot,
          apiUrl: umiOcrApiUrl,
          language: umiOcrLanguage,
        })
        
        if (!ocrResult.success) {
          alert(`Umi-OCR 识别失败: ${ocrResult.error}`)
          return
        }
        
        text = ocrResult.text || ''
        confidence = 1.0 // Umi-OCR 不提供置信度，默认为 1.0
        elapsed = ocrResult.elapsed || 0
      } else {
        // 使用 Tesseract 引擎
        console.log('[OCR测试] 使用 Tesseract 引擎识别...')
        if (!ocrWorkerRef.current) {
          alert('Tesseract 引擎未初始化')
          return
        }
        
        const startTime = performance.now()
        const { data: { text: ocrText, confidence: ocrConfidence } } = await ocrWorkerRef.current.recognize(result.processedScreenshot)
        elapsed = Math.round(performance.now() - startTime)
        
        text = ocrText
        confidence = ocrConfidence || 0
      }
      
      console.log(`[OCR测试] 识别完成，耗时: ${elapsed}ms，置信度: ${(confidence * 100).toFixed(1)}%`)
      console.log('[OCR测试] 识别文本:', text)
      
      setOcrTestResult({
        originalImage: result.screenshot,
        processedImage: result.processedScreenshot,
        text: text,
        confidence: confidence,
        elapsed: elapsed
      })
    } catch (error) {
      console.error('[OCR测试] 失败:', error)
      alert('OCR测试失败，请重试')
    } finally {
      setIsTestingOCR(false)
    }
  }

  // 开始选择区域
  const handleStartSelectRegion = async () => {
    try {
      console.log('[区域选择] 开始截图...')
      const result = await window.ipcRenderer.invoke('liveWakeup:capturePreview')
      if (result.success && result.screenshot) {
        setRegionSelectImage(result.screenshot)
        setIsSelectingRegion(true)
        console.log('[区域选择] 截图成功，进入选择模式')
      } else {
        alert(`截图失败: ${result.error || '未知错误'}`)
      }
    } catch (error) {
      console.error('[区域选择] 截图失败:', error)
      alert('截图失败，请重试')
    }
  }

  // 取消选择区域
  const handleCancelSelectRegion = () => {
    setIsSelectingRegion(false)
    setRegionSelectImage(null)
  }

  // 清除选择的区域
  const handleClearRegion = () => {
    setCaptureRegion(null)
    localStorage.removeItem('liveWakeup:captureRegion')
    console.log('[区域选择] 已清除选择区域，将截取整个屏幕')
  }

  // 确认选择区域
  const handleConfirmRegion = (region: { x: number; y: number; width: number; height: number }) => {
    setCaptureRegion(region)
    localStorage.setItem('liveWakeup:captureRegion', JSON.stringify(region))
    setIsSelectingRegion(false)
    setRegionSelectImage(null)
    console.log('[区域选择] 已选择区域并保存:', region)
  }

  // 打开悬浮窗
  const handleOpenFloatingWindow = async () => {
    try {
      const result = await window.ipcRenderer.invoke('liveWakeup:openFloatingWindow' as any)
      if (result && 'success' in result && !result.success) {
        alert(`打开悬浮窗失败: ${result.error}`)
      }
    } catch (error) {
      console.error('[悬浮窗] 打开失败:', error)
      alert('打开悬浮窗失败')
    }
  }


  // 监听监控停止事件
  useEffect(() => {
    const unsubscribe = window.ipcRenderer.on('liveWakeup:stoppedEvent', () => {
      console.log('📩 收到主进程停止事件')
      isMonitoringRef.current = false
      setIsMonitoring(false)
      // 不自动停止警报，让用户手动点击"停止警报"按钮
      // stopAlert()
    })

    return () => {
      unsubscribe()
    }
  }, [stopAlert])

  // 图像匹配功能已删除，不再需要监听 alertTriggered 事件

  // 添加关键词
  const handleAddKeyword = () => {
    if (newKeyword.trim() && !keywords.includes(newKeyword.trim())) {
      const newKeywords = [...keywords, newKeyword.trim()]
      setKeywords(newKeywords)
      localStorage.setItem('liveWakeup:keywords', JSON.stringify(newKeywords))
      setNewKeyword('')
    }
  }

  // 删除关键词
  const handleRemoveKeyword = (keyword: string) => {
    const newKeywords = keywords.filter(k => k !== keyword)
    setKeywords(newKeywords)
    localStorage.setItem('liveWakeup:keywords', JSON.stringify(newKeywords))
  }

  // 叫醒模式相关处理函数
  const handleWakeupModeChange = (mode: 'audio' | 'phone') => {
    setWakeupMode(mode)
    localStorage.setItem('liveWakeup:wakeupMode', mode)
  }

  const handleAudioFileSelect = async () => {
    try {
      // 调用主进程的文件选择对话框
      const result = await window.ipcRenderer.invoke('dialog:openFile' as any, {
        filters: [
          { name: '音频文件', extensions: ['mp3', 'wav', 'ogg', 'aac', 'flac'] },
          { name: '所有文件', extensions: ['*'] }
        ],
        properties: ['openFile']
      }) as { canceled: boolean; filePaths: string[] }
      
      if (result && !result.canceled && result.filePaths && result.filePaths.length > 0) {
        const filePath = result.filePaths[0]
        setAudioFilePath(filePath)
        localStorage.setItem('liveWakeup:audioFilePath', filePath)
      }
    } catch (error) {
      console.error('选择音频文件失败:', error)
      alert('选择音频文件失败')
    }
  }

  const handlePhoneNumberChange = (value: string) => {
    setPhoneNumber(value)
    localStorage.setItem('liveWakeup:phoneNumber', value)
  }

  // 初始化阿里云服务（从配置文件）
  const handleInitAliCloudService = async () => {
    if (!aliCloudConfigStatus.isConfigured) {
      alert('请先配置 config/alicloud-voice.json 文件')
      return
    }

    try {
      const result = await window.ipcRenderer.invoke('liveWakeup:initAliCloudVoiceFromConfig' as any) as VoiceCallResult
      
      if (result.success) {
        setAliCloudConfigStatus(prev => ({ ...prev, initialized: true }))
        alert('阿里云语音服务初始化成功！')
      } else {
        alert(`初始化失败: ${result.error}`)
      }
    } catch (error) {
      console.error('初始化阿里云服务失败:', error)
      alert('初始化失败，请检查网络连接和配置文件')
    }
  }

  const handleTestPhoneCall = async () => {
    if (!phoneNumber.trim()) {
      alert('请先输入电话号码')
      return
    }

    if (!aliCloudConfigStatus.initialized) {
      alert('请先初始化阿里云语音服务')
      return
    }

    try {
      const result = await window.ipcRenderer.invoke('liveWakeup:testPhoneCall' as any, {
        phoneNumber: phoneNumber.trim()
      }) as VoiceCallResult
      
      if (result.success) {
        alert(`测试电话拨打成功！通话ID: ${result.callId}`)
      } else {
        alert(`测试失败: ${result.error}`)
      }
    } catch (error) {
      console.error('测试电话失败:', error)
      alert('测试电话失败，请检查网络连接')
    }
  }

  const handleTestAudioPlay = async () => {
    if (!audioFilePath) {
      alert('请先选择音频文件')
      return
    }

    try {
      console.log('开始测试播放音频:', audioFilePath)
      
      // 使用IPC通道播放音频文件
      const result = await window.ipcRenderer.invoke('liveWakeup:playAudioFile', {
        filePath: audioFilePath,
        volume: alertVolume[0]
      })

      if (result.success) {
        console.log('音频播放请求发送成功')
      } else {
        console.error('音频播放失败:', result.error)
        alert(`音频播放失败: ${result.error}`)
      }
    } catch (error) {
      console.error('测试音频播放失败:', error)
      alert('音频播放失败，请检查文件格式或路径')
    }
  }

  // 保存检测间隔到 localStorage
  useEffect(() => {
    localStorage.setItem('liveWakeup:checkInterval', checkInterval[0].toString())
  }, [checkInterval])

  // 保存警报循环次数到 localStorage
  useEffect(() => {
    localStorage.setItem('liveWakeup:alertRepeat', alertRepeat[0].toString())
  }, [alertRepeat])

  // 保存警报音量到 localStorage
  useEffect(() => {
    localStorage.setItem('liveWakeup:alertVolume', alertVolume[0].toString())
  }, [alertVolume])

  // 保存预处理模式到 localStorage
  useEffect(() => {
    localStorage.setItem('liveWakeup:preprocessMode', preprocessMode)
  }, [preprocessMode])

  // 保存 OCR 引擎配置到 localStorage
  useEffect(() => {
    localStorage.setItem('liveWakeup:ocrEngine', ocrEngine)
  }, [ocrEngine])

  useEffect(() => {
    localStorage.setItem('liveWakeup:umiOcrApiUrl', umiOcrApiUrl)
  }, [umiOcrApiUrl])

  useEffect(() => {
    localStorage.setItem('liveWakeup:umiOcrLanguage', umiOcrLanguage)
  }, [umiOcrLanguage])

  // 启动监控
  const handleStart = async () => {
    console.log('[启动监控] 🚀 开始启动流程...')
    
    // 验证OCR
    if (keywords.length === 0) {
      alert('请至少添加一个关键词')
      return
    }

    if (!ocrReady) {
      alert('OCR 引擎正在初始化中，请稍候...')
      return
    }

    try {
      console.log('[启动监控] ⏱️ 开始构建配置对象...')
      const config: LiveWakeupConfig = {
        keywords,
        checkInterval: checkInterval[0],
        saveScreenshot,
        alertVolume: alertVolume[0],
        alertRepeat: alertRepeat[0],
        ocrLanguage: 'chi_sim',
        captureRegion: captureRegion || undefined,
        detectionMode: 'ocr', // 只使用OCR模式
        preprocessMode: preprocessMode, // 添加预处理模式
        // 添加叫醒模式配置
        wakeupMode: {
          type: wakeupMode,
          phoneNumber: wakeupMode === 'phone' ? phoneNumber.trim() : undefined,
          audioFilePath: wakeupMode === 'audio' ? audioFilePath : undefined,
        },
        // OCR引擎配置
        ocrEngine: {
          engine: ocrEngine,
          tesseract: {
            language: 'chi_sim',
          },
          umiOcr: ocrEngine === 'umi-ocr' ? {
            apiUrl: umiOcrApiUrl,
            language: umiOcrLanguage,
            timeout: 10000,
          } : undefined,
        },
      }
      console.log('[启动监控] ✅ 配置对象构建完成，叫醒模式:', wakeupMode)
      
      console.log('[启动监控] 📡 调用 IPC，等待主进程响应...')
      const startTime = performance.now()
      const result = await window.ipcRenderer.invoke('liveWakeup:start', config)
      const elapsed = Math.round(performance.now() - startTime)
      console.log(`[启动监控] ✅ IPC 调用完成，耗时: ${elapsed}ms`)
      
      if (result.success) {
        isMonitoringRef.current = true // 立即更新 ref
        setIsMonitoring(true)
        console.log('✅ 监控已启动')
      } else {
        alert(`启动失败: ${result.error}`)
      }
    } catch (error) {
      console.error('启动监控失败:', error)
      alert('启动失败，请检查配置')
    }
  }

  // 停止监控
  const handleStop = async () => {
    try {
      console.log('🛑 用户点击停止监控')
      // 立即更新 ref，阻止新的 OCR 请求
      isMonitoringRef.current = false
      setIsMonitoring(false)
      
      // 调用主进程停止
      await window.ipcRenderer.invoke('liveWakeup:stop')
      
      // 不自动停止警报，让用户手动点击"停止警报"按钮
      // stopAlert()
      
      console.log('✅ 监控已停止')
    } catch (error) {
      console.error('停止监控失败:', error)
    }
  }

  return (
    <div className="container py-8 space-y-6">
      <div>
        <Title 
          title="直播叫醒" 
          description="自动检测屏幕上的人脸识别弹窗并及时提醒" 
        />
      </div>

      {/* 警报状态提示 */}
      {alertActive && (
        <Card className="p-6 bg-red-50 dark:bg-red-950 border-red-500 animate-pulse">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <AlertCircle className="h-8 w-8 text-red-500" />
              <div>
                <h3 className="text-lg font-bold text-red-700 dark:text-red-300">
                  ⚠️ 检测到关键词：{lastAlert?.keyword}
                </h3>
                <p className="text-sm text-red-600 dark:text-red-400">
                  {lastAlert && new Date(lastAlert.timestamp).toLocaleString()}
                </p>
              </div>
            </div>
            <Button onClick={stopAlert} variant="destructive" size="lg">
              停止警报
            </Button>
          </div>
          {lastAlert?.screenshot && (
            <div className="mt-4">
              <img 
                src={lastAlert.screenshot} 
                alt="截图" 
                className="max-w-full max-h-64 rounded border"
              />
            </div>
          )}
        </Card>
      )}

      {/* 监控状态 */}
      <Card className="p-6">
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-3">
            <div className={`h-3 w-3 rounded-full ${isMonitoring ? 'bg-green-500 animate-pulse' : 'bg-gray-400'}`} />
            <div>
              <h3 className="text-lg font-semibold">
                监控状态: {isMonitoring ? '运行中' : '已停止'}
              </h3>
              <p className="text-sm text-muted-foreground">
                {isMonitoring ? `每 ${checkInterval[0]} 秒检测一次 (OCR文字识别)` : '点击启动按钮开始监控'}
              </p>
              <p className="text-xs text-muted-foreground mt-1">
                OCR 引擎: {ocrReady ? '✅ 已就绪（自适应增强模式）' : '⏳ 初始化中...'}
              </p>
            </div>
          </div>
          <div className="flex gap-2">
            <Button
              onClick={handleTestScreenshot}
              size="lg"
              variant="outline"
              disabled={isTestingScreenshot}
            >
              {isTestingScreenshot ? '截图中...' : '测试截图'}
            </Button>
            <Button
              onClick={handleTestOCR}
              size="lg"
              variant="outline"
              disabled={isTestingOCR || !ocrReady}
              title="测试OCR识别效果，建议先打开一个包含文字的窗口（如网页）再测试"
            >
              {isTestingOCR ? '识别中...' : '测试OCR'}
            </Button>
            <Button
              onClick={isMonitoring ? handleStop : handleStart}
              size="lg"
              variant={isMonitoring ? 'destructive' : 'default'}
              className="min-w-32"
              disabled={!isMonitoring && !ocrReady}
            >
              {isMonitoring ? (
                <>
                  <Pause className="mr-2 h-5 w-5" />
                  停止监控
                </>
              ) : (
                <>
                  <Play className="mr-2 h-5 w-5" />
                  启动监控
                </>
              )}
            </Button>
          </div>
        </div>

        {/* 悬浮窗提示 */}
        <div className="p-4 bg-blue-50 dark:bg-blue-950 rounded-lg border border-blue-200 dark:border-blue-800">
          <div className="flex items-start justify-between">
            <div className="flex-1">
              <h4 className="text-sm font-semibold text-blue-900 dark:text-blue-100 mb-1">
                💡 使用悬浮窗更方便
              </h4>
              <p className="text-xs text-blue-700 dark:text-blue-300">
                悬浮窗始终置顶显示，不会遮挡直播伴侣，方便随时查看监控状态
              </p>
            </div>
            <Button
              onClick={handleOpenFloatingWindow}
              size="sm"
              variant="outline"
              className="ml-4 border-blue-300 dark:border-blue-700 hover:bg-blue-100 dark:hover:bg-blue-900"
            >
              <ExternalLink className="mr-2 h-4 w-4" />
              打开悬浮窗
            </Button>
          </div>
        </div>
        
        {/* 测试截图预览 */}
        {testScreenshot && (
          <div className="mt-4 p-4 bg-muted/50 rounded-lg">
            <div className="flex items-center justify-between mb-2">
              <h4 className="text-sm font-semibold">测试截图预览</h4>
              <Button
                onClick={() => setTestScreenshot(null)}
                size="sm"
                variant="ghost"
              >
                <X className="h-4 w-4" />
              </Button>
            </div>
            <img 
              src={testScreenshot} 
              alt="测试截图" 
              className="max-w-full max-h-96 rounded border"
            />
          </div>
        )}
        
        {/* OCR测试结果 */}
        {ocrTestResult && (
          <div className="mt-4 p-4 bg-green-50 dark:bg-green-950 rounded-lg border border-green-200 dark:border-green-800">
            <div className="flex items-center justify-between mb-3">
              <div className="flex-1">
                <h4 className="text-sm font-semibold text-green-900 dark:text-green-100">OCR识别测试结果</h4>
                <div className="flex gap-4 mt-1 text-xs text-green-700 dark:text-green-300">
                  <span>置信度: {(ocrTestResult.confidence * 100).toFixed(1)}%</span>
                  <span>耗时: {ocrTestResult.elapsed}ms</span>
                  <span>字符数: {ocrTestResult.text.length}</span>
                </div>
                {ocrTestResult.text.length === 0 && (
                  <p className="text-xs text-orange-600 dark:text-orange-400 mt-1">
                    ⚠️ 未识别到文字，请确保截图区域包含清晰的文字内容
                  </p>
                )}
              </div>
              <Button
                onClick={() => setOcrTestResult(null)}
                size="sm"
                variant="ghost"
              >
                <X className="h-4 w-4" />
              </Button>
            </div>
            
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-3">
              <div>
                <p className="text-xs font-medium text-green-800 dark:text-green-200 mb-1">原始图像</p>
                <img 
                  src={ocrTestResult.originalImage} 
                  alt="原始图像" 
                  className="w-full rounded border border-green-300 dark:border-green-700"
                />
              </div>
              <div>
                <p className="text-xs font-medium text-green-800 dark:text-green-200 mb-1">预处理后（OCR识别用）</p>
                <img 
                  src={ocrTestResult.processedImage} 
                  alt="预处理图像" 
                  className="w-full rounded border border-green-300 dark:border-green-700"
                />
              </div>
            </div>
            
            <div>
              <p className="text-xs font-medium text-green-800 dark:text-green-200 mb-1">识别文本</p>
              <div className="p-3 bg-white dark:bg-gray-900 rounded border border-green-300 dark:border-green-700 max-h-40 overflow-y-auto">
                <pre className="text-xs whitespace-pre-wrap font-mono text-gray-800 dark:text-gray-200">
                  {ocrTestResult.text || '(未识别到文字)'}
                </pre>
              </div>
            </div>
          </div>
        )}
      </Card>

      {/* 配置面板 */}
      <Card className="p-4 space-y-4">
        <h3 className="text-base font-semibold">监控配置</h3>

        {/* OCR引擎选择 */}
        <div className="space-y-2">
          <Label className="text-sm">OCR引擎</Label>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-2">
            {/* Tesseract.js */}
            <div 
              className={`p-3 border rounded-md cursor-pointer transition-all ${
                ocrEngine === 'tesseract' 
                  ? 'border-primary bg-primary/5' 
                  : 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
              }`}
              onClick={() => setOcrEngine('tesseract')}
            >
              <div className="flex items-center gap-2">
                <div className={`w-3 h-3 rounded-full border-2 ${
                  ocrEngine === 'tesseract' 
                    ? 'border-primary bg-primary' 
                    : 'border-gray-300 dark:border-gray-600'
                }`} />
                <div>
                  <h4 className="font-medium text-xs">Tesseract.js</h4>
                  <p className="text-xs text-muted-foreground">浏览器内置OCR，无需配置</p>
                </div>
              </div>
            </div>

            {/* Umi-OCR */}
            <div 
              className={`p-3 border rounded-md cursor-pointer transition-all ${
                ocrEngine === 'umi-ocr' 
                  ? 'border-primary bg-primary/5' 
                  : 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
              }`}
              onClick={() => setOcrEngine('umi-ocr')}
            >
              <div className="flex items-center gap-2">
                <div className={`w-3 h-3 rounded-full border-2 ${
                  ocrEngine === 'umi-ocr' 
                    ? 'border-primary bg-primary' 
                    : 'border-gray-300 dark:border-gray-600'
                }`} />
                <div>
                  <h4 className="font-medium text-xs">Umi-OCR</h4>
                  <p className="text-xs text-muted-foreground">高精度OCR，需本地服务</p>
                </div>
              </div>
            </div>
          </div>

          {/* Umi-OCR 配置 */}
          {ocrEngine === 'umi-ocr' && (
            <div className="mt-2 p-3 bg-muted/50 rounded-md space-y-3">
              <div className="space-y-1">
                <Label className="text-xs">API 地址</Label>
                <Input
                  value={umiOcrApiUrl}
                  onChange={(e) => setUmiOcrApiUrl(e.target.value)}
                  placeholder="http://127.0.0.1:1224"
                  className="h-8 text-xs"
                />
                <p className="text-xs text-muted-foreground">
                  请确保 Umi-OCR 服务已启动
                </p>
              </div>
              <div className="space-y-1">
                <Label className="text-xs">语言代码</Label>
                <Input
                  value={umiOcrLanguage}
                  onChange={(e) => setUmiOcrLanguage(e.target.value)}
                  placeholder="chi_sim"
                  className="h-8 text-xs"
                />
                <p className="text-xs text-muted-foreground">
                  默认 chi_sim (简体中文)
                </p>
              </div>
            </div>
          )}
        </div>

        {/* 关键词设置 */}
        <div className="space-y-2">
          <Label className="text-sm">检测关键词</Label>
          <div className="p-3 bg-blue-50 dark:bg-blue-950 rounded border border-blue-200 dark:border-blue-800 mb-2">
            <p className="text-xs text-blue-700 dark:text-blue-300">
              通过OCR识别屏幕文字，适合文字提示类验证
            </p>
          </div>
          <div className="flex gap-2">
            <Input
              value={newKeyword}
              onChange={(e) => setNewKeyword(e.target.value)}
              placeholder="输入关键词，如：人脸识别"
              className="text-sm h-8"
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  handleAddKeyword()
                }
              }}
            />
            <Button onClick={handleAddKeyword} variant="outline" size="sm" className="h-8 px-3">
              <Plus className="h-3 w-3" />
            </Button>
          </div>
          <div className="flex flex-wrap gap-1">
            {keywords.map((keyword) => (
              <Badge key={keyword} variant="secondary" className="text-xs py-1 px-2">
                {keyword}
                <button
                  onClick={() => handleRemoveKeyword(keyword)}
                  className="ml-1 hover:text-red-500"
                >
                  <X className="h-2 w-2" />
                </button>
              </Badge>
            ))}
          </div>
        </div>

        {/* 叫醒模式配置 */}
        <div className="space-y-2">
          <Label className="text-sm">叫醒模式</Label>
          
          <div className="grid grid-cols-1 md:grid-cols-2 gap-2">
            {/* 播放音频模式 */}
            <div 
              className={`p-3 border rounded-md cursor-pointer transition-all ${
                wakeupMode === 'audio' 
                  ? 'border-primary bg-primary/5' 
                  : 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
              }`}
              onClick={() => handleWakeupModeChange('audio')}
            >
              <div className="flex items-center gap-2 mb-2">
                <div className={`p-1 rounded-full ${
                  wakeupMode === 'audio' ? 'bg-primary text-primary-foreground' : 'bg-gray-100 dark:bg-gray-800'
                }`}>
                  <Volume2 className="h-3 w-3" />
                </div>
                <div>
                  <h4 className="font-medium text-xs">播放音频</h4>
                </div>
              </div>
              
              {wakeupMode === 'audio' && (
                <div className="space-y-2 pt-2 border-t border-gray-200 dark:border-gray-700">
                  <div className="grid grid-cols-1 gap-2">
                    <Button
                      onClick={(e) => {
                        e.stopPropagation()
                        handleAudioFileSelect()
                      }}
                      variant="outline"
                      size="sm"
                      className="w-full text-xs h-7"
                    >
                      <FileAudio className="mr-1 h-3 w-3" />
                      选择音频
                    </Button>
                    
                    {audioFilePath && (
                      <Button
                        onClick={(e) => {
                          e.stopPropagation()
                          handleTestAudioPlay()
                        }}
                        variant="outline"
                        size="sm"
                        className="w-full text-xs h-7"
                      >
                        <PlayCircle className="mr-1 h-3 w-3" />
                        测试播放
                      </Button>
                    )}
                  </div>
                  
                  {audioFilePath && (
                    <div className="p-2 bg-green-50 dark:bg-green-950 rounded border border-green-200 dark:border-green-800">
                      <div className="flex items-center justify-between gap-2">
                        <p className="text-xs text-green-700 dark:text-green-300 font-mono break-all flex-1">
                          ✓ {audioFilePath.split(/[/\\]/).pop()}
                        </p>
                        <button
                          onClick={(e) => {
                            e.stopPropagation()
                            setAudioFilePath('')
                            localStorage.removeItem('liveWakeup:audioFilePath')
                          }}
                          className="flex-shrink-0 p-1 hover:bg-red-500/20 rounded transition-colors"
                          title="清除音频文件"
                        >
                          <X className="h-3 w-3 text-red-600 dark:text-red-400" />
                        </button>
                      </div>
                    </div>
                  )}
                </div>
              )}
            </div>

            {/* 电话叫醒模式 */}
            <div 
              className={`p-3 border rounded-md cursor-pointer transition-all ${
                wakeupMode === 'phone' 
                  ? 'border-primary bg-primary/5' 
                  : 'border-gray-200 dark:border-gray-700 hover:border-gray-300 dark:hover:border-gray-600'
              }`}
              onClick={() => handleWakeupModeChange('phone')}
            >
              <div className="flex items-center gap-2 mb-2">
                <div className={`p-1 rounded-full ${
                  wakeupMode === 'phone' ? 'bg-primary text-primary-foreground' : 'bg-gray-100 dark:bg-gray-800'
                }`}>
                  <Phone className="h-3 w-3" />
                </div>
                <div>
                  <h4 className="font-medium text-xs">电话叫醒</h4>
                </div>
              </div>
              
              {wakeupMode === 'phone' && (
                <div className="space-y-2 pt-2 border-t border-gray-200 dark:border-gray-700">
                  {/* 阿里云配置状态 */}
                  <div className="p-2 bg-blue-50 dark:bg-blue-950 rounded border border-blue-200 dark:border-blue-800">
                    <div className="flex items-center justify-between mb-2">
                      <span className="text-xs font-medium text-blue-900 dark:text-blue-100">
                        阿里云语音服务
                      </span>
                      {aliCloudConfigStatus.initialized ? (
                        <span className="text-xs text-green-600 dark:text-green-400">✅ 已初始化</span>
                      ) : aliCloudConfigStatus.isConfigured ? (
                        <span className="text-xs text-orange-600 dark:text-orange-400">⚡ 需要初始化</span>
                      ) : (
                        <span className="text-xs text-red-600 dark:text-red-400">❌ 未配置</span>
                      )}
                    </div>
                    
                    {aliCloudConfigStatus.isConfigured ? (
                      <div className="space-y-1">
                        <div className="text-xs text-blue-700 dark:text-blue-300">
                          ✓ 配置文件已加载 (来源: {aliCloudConfigStatus.source === 'file' ? '配置文件' : '手动'})
                        </div>
                        <Button
                          onClick={(e) => {
                            e.stopPropagation()
                            handleInitAliCloudService()
                          }}
                          variant="outline"
                          size="sm"
                          className="w-full text-xs h-6"
                        >
                          {aliCloudConfigStatus.initialized ? '重新初始化' : '初始化服务'}
                        </Button>
                      </div>
                    ) : (
                      <div className="text-xs text-red-700 dark:text-red-300">
                        请配置 config/alicloud-voice.json 文件
                        {aliCloudConfigStatus.error && (
                          <div className="mt-1 text-red-600 dark:text-red-400">
                            错误: {aliCloudConfigStatus.error}
                          </div>
                        )}
                      </div>
                    )}
                  </div>

                  {/* 电话号码输入 */}
                  <Input
                    value={phoneNumber}
                    onChange={(e) => handlePhoneNumberChange(e.target.value)}
                    placeholder="手机号码"
                    onClick={(e) => e.stopPropagation()}
                    className="text-xs h-7"
                  />
                  
                  <Button
                    onClick={(e) => {
                      e.stopPropagation()
                      handleTestPhoneCall()
                    }}
                    variant="outline"
                    size="sm"
                    className="w-full text-xs h-7"
                    disabled={!phoneNumber.trim() || !aliCloudConfigStatus.initialized}
                  >
                    <TestTube className="mr-1 h-3 w-3" />
                    测试通话
                  </Button>
                </div>
              )}
            </div>
          </div>
        </div>

        {/* 图像预处理模式 */}
        <div className="space-y-2">
          <Label className="text-sm">图像预处理模式</Label>
          <div className="grid grid-cols-2 md:grid-cols-4 gap-2">
            <button
              onClick={() => setPreprocessMode('none')}
              className={`p-2 text-xs rounded border transition-all ${
                preprocessMode === 'none'
                  ? 'bg-primary text-primary-foreground border-primary'
                  : 'bg-background hover:bg-muted border-border'
              }`}
            >
              <div className="font-medium">关闭</div>
              <div className="text-xs opacity-70">原始图像</div>
            </button>
            <button
              onClick={() => setPreprocessMode('light')}
              className={`p-2 text-xs rounded border transition-all ${
                preprocessMode === 'light'
                  ? 'bg-primary text-primary-foreground border-primary'
                  : 'bg-background hover:bg-muted border-border'
              }`}
            >
              <div className="font-medium">轻度</div>
              <div className="text-xs opacity-70">推荐</div>
            </button>
            <button
              onClick={() => setPreprocessMode('standard')}
              className={`p-2 text-xs rounded border transition-all ${
                preprocessMode === 'standard'
                  ? 'bg-primary text-primary-foreground border-primary'
                  : 'bg-background hover:bg-muted border-border'
              }`}
            >
              <div className="font-medium">标准</div>
              <div className="text-xs opacity-70">平衡</div>
            </button>
            <button
              onClick={() => setPreprocessMode('strong')}
              className={`p-2 text-xs rounded border transition-all ${
                preprocessMode === 'strong'
                  ? 'bg-primary text-primary-foreground border-primary'
                  : 'bg-background hover:bg-muted border-border'
              }`}
            >
              <div className="font-medium">强力</div>
              <div className="text-xs opacity-70">高对比</div>
            </button>
          </div>
          <p className="text-xs text-muted-foreground">
            {preprocessMode === 'none' && '⚠️ 不进行预处理，识别率可能较低'}
            {preprocessMode === 'light' && '✅ 轻度增强，适合大多数场景（推荐）'}
            {preprocessMode === 'standard' && '⚡ 标准增强，适合对比度较低的场景'}
            {preprocessMode === 'strong' && '🔥 强力增强，适合暗色背景或模糊文字'}
          </p>
        </div>

        {/* 监控区域 */}
        <div className="space-y-2">
          <Label className="text-sm">监控区域</Label>
          <div className="p-2 bg-blue-50 dark:bg-blue-950 rounded border border-blue-200 dark:border-blue-800 mb-2">
            <p className="text-xs text-blue-700 dark:text-blue-300">
              💡 <strong>重要：</strong>请选择弹窗可能出现的区域（如直播画面中央），避免选择空白/黑色背景
            </p>
          </div>
          <div className="flex gap-2">
            <Button 
              onClick={handleStartSelectRegion} 
              variant="outline" 
              size="sm"
              className="flex-1 text-xs h-8"
              disabled={isMonitoring}
            >
              <Crop className="mr-1 h-3 w-3" />
              {captureRegion ? '重选区域' : '选择区域'}
            </Button>
            {captureRegion && (
              <Button 
                onClick={handleClearRegion} 
                variant="outline"
                size="sm"
                className="h-8 px-3"
                disabled={isMonitoring}
              >
                <X className="h-3 w-3" />
              </Button>
            )}
          </div>
          {captureRegion ? (
            <div className="p-2 bg-green-50 dark:bg-green-950 rounded border border-green-200 dark:border-green-800">
              <div className="flex items-center justify-between text-xs">
                <span className="text-green-700 dark:text-green-300">✅ 已选择区域</span>
                <span className="text-green-600 dark:text-green-400 font-mono">
                  {captureRegion.width}×{captureRegion.height}
                </span>
              </div>
            </div>
          ) : (
            <p className="text-xs text-muted-foreground">
              ⚠️ 未选择区域时将监控整个屏幕（识别速度较慢）
            </p>
          )}
        </div>

        {/* 检测参数 - 合并为两列布局 */}
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          {/* 检测间隔 */}
          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <Label className="text-sm">检测间隔</Label>
              <span className="text-xs font-medium text-muted-foreground">{checkInterval[0]}秒</span>
            </div>
            <Slider
              value={checkInterval}
              onValueChange={setCheckInterval}
              min={1}
              max={30}
              step={1}
              className="h-1"
            />
          </div>

          {/* 警报音量 */}
          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <Label className="text-sm">警报音量</Label>
              <span className="text-xs font-medium text-muted-foreground">{alertVolume[0]}%</span>
            </div>
            <Slider
              value={alertVolume}
              onValueChange={setAlertVolume}
              min={0}
              max={100}
              step={1}
              className="h-1"
            />
          </div>
        </div>

        {/* 警报循环次数 */}
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <Label className="text-sm">警报循环</Label>
            <span className="text-xs font-medium text-muted-foreground">
              {alertRepeat[0] === 0 ? '无限' : `${alertRepeat[0]}次`}
            </span>
          </div>
          <Slider
            value={alertRepeat}
            onValueChange={setAlertRepeat}
            min={0}
            max={10}
            step={1}
            className="h-1"
          />
        </div>

        {/* 保存截图 */}
        <div className="flex items-center justify-between p-3 bg-muted/30 rounded-md">
          <div>
            <Label htmlFor="save-screenshot" className="cursor-pointer text-sm">
              保存触发截图
            </Label>
          </div>
          <Switch
            id="save-screenshot"
            checked={saveScreenshot}
            onCheckedChange={setSaveScreenshot}
          />
        </div>
      </Card>

      {/* OCR识别日志 */}
      {ocrLogs.length > 0 && (
        <Card className="p-4">
          <div className="flex items-center justify-between mb-3">
            <h3 className="text-base font-semibold">OCR识别日志</h3>
            <Button
              onClick={() => setOcrLogs([])}
              size="sm"
              variant="ghost"
            >
              清空日志
            </Button>
          </div>
          <div className="space-y-2 max-h-80 overflow-y-auto">
            {ocrLogs.map((log, index) => (
              <div
                key={index}
                className={`p-3 rounded border text-xs ${
                  log.matched
                    ? 'bg-red-50 dark:bg-red-950 border-red-300 dark:border-red-700'
                    : 'bg-gray-50 dark:bg-gray-900 border-gray-200 dark:border-gray-700'
                }`}
              >
                <div className="flex items-start justify-between mb-2">
                  <div className="flex items-center gap-2">
                    <span className={`font-medium ${
                      log.matched 
                        ? 'text-red-700 dark:text-red-300' 
                        : 'text-gray-700 dark:text-gray-300'
                    }`}>
                      {log.matched ? '✅ 匹配成功' : '❌ 未匹配'}
                    </span>
                    {log.matched && log.keyword && (
                      <Badge variant="destructive" className="text-xs">
                        {log.keyword}
                      </Badge>
                    )}
                  </div>
                  <span className="text-gray-500 dark:text-gray-400 text-xs">
                    {new Date(log.timestamp).toLocaleTimeString()}
                  </span>
                </div>
                <div className="flex items-center gap-3 text-xs text-gray-600 dark:text-gray-400 mb-1">
                  <span>置信度: {(log.confidence * 100).toFixed(1)}%</span>
                  <span>长度: {log.text.length}字符</span>
                </div>
                <div className="p-2 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-600 max-h-24 overflow-y-auto">
                  <pre className="text-xs whitespace-pre-wrap font-mono text-gray-700 dark:text-gray-300">
                    {log.text || '(未识别到文字)'}
                  </pre>
                </div>
              </div>
            ))}
          </div>
        </Card>
      )}

      {/* 使用说明 */}
      <Card className="p-3 bg-blue-50/50 dark:bg-blue-950/50">
        <div className="flex items-start gap-2">
          <BellRing className="h-4 w-4 text-blue-500 mt-0.5" />
          <div>
            <h4 className="font-medium text-sm text-blue-900 dark:text-blue-100 mb-1">使用说明</h4>
            <div className="text-xs text-blue-700 dark:text-blue-300 space-y-0.5">
              <p>• <strong>测试OCR前：</strong>打开一个包含清晰文字的窗口（网页、文档等），然后点击"测试OCR"</p>
              <p>• <strong>选择监控区域：</strong>框选弹窗可能出现的位置（避免空白区域），提高识别准确率</p>
              <p>• <strong>添加关键词：</strong>使用弹窗中最明显、独特的文字（如"身份验证"、"人脸识别"）</p>
              <p>• <strong>启动监控：</strong>设置好参数后点击"启动监控"，检测到关键词将自动提醒</p>
            </div>
          </div>
        </div>
      </Card>

      {/* 区域选择器 */}
      {isSelectingRegion && regionSelectImage && (
        <RegionSelector
          imageUrl={regionSelectImage}
          onConfirm={handleConfirmRegion}
          onCancel={handleCancelSelectRegion}
        />
      )}
    </div>
  )
}
